package cn.exrick.xboot.index.service.serviceimpl;

import cn.exrick.xboot.common.utils.DateUtil;
import cn.exrick.xboot.common.utils.ResultUtil;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.index.entity.ParamVo;
import cn.exrick.xboot.index.mapper.IndexMapper;
import cn.exrick.xboot.modules.base.utils.DateUtils;
import cn.exrick.xboot.modules.content.dao.HontLogDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
@Slf4j
public class IndexServiceImpl {


    @Autowired
    private IndexMapper indexMapper;
    @Autowired
    private HontLogDao hontLogDao;
    public Result<Object> countIndexHead(){
        Map<String, Object> map=new HashMap<>();
        int countHontLog=indexMapper.countHontLog();
        int countInstanceinfo=indexMapper.countInstanceinfo();
        int countInstanceinfoByMouth=indexMapper.countInstanceinfoByMouth();
        int sumInstanceinfoTime=indexMapper.sumInstanceinfoTime();
        long avgInstanceinfoTime;
        if(countInstanceinfoByMouth>0){
             avgInstanceinfoTime= sumInstanceinfoTime/countInstanceinfoByMouth;
        }else{
             avgInstanceinfoTime=sumInstanceinfoTime;
        }
        int timeOut=indexMapper.countTimeOut();
        map.put("countHontLog",countHontLog);
        map.put("countInstanceinfo",countInstanceinfo);
        map.put("avgInstanceinfoTime",avgInstanceinfoTime);
        map.put("timeOut",timeOut);
        return ResultUtil.data(map);
    }
    public void getDateTime(ParamVo param){

        switch(param.getSelectType()){
            case ParamVo.day: {
                param.setBeginDate(DateUtils.getCurrentDate() + " 00:00:00");
                param.setEndDate(DateUtils.getCurrentDate() + " 23:59:59");
                break;
            }
            case ParamVo.week: {
                param.setBeginDate( DateUtils.getCurrentWeekFirstDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_FORMATTER))+ " 00:00:00");
                param.setEndDate(DateUtils.getCurrentWeekLastDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_FORMATTER))+ " 23:59:59");
                break;
            }
            case ParamVo.month: {
                param.setBeginDate( DateUtils.getCurrentMonthFirstDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_FORMATTER))+ " 00:00:00");
                param.setEndDate( DateUtils.getCurrentMonthLastDate().format(DateTimeFormatter.ofPattern(DateUtils.DATE_FORMATTER))+ " 23:59:59");
                break;
            }
            default: {
                param.setBeginDate(param.getBeginDate()+ " 00:00:00");
                param.setEndDate(param.getEndDate()+ " 23:59:59");
                break;
            }
        }
    }
    public  Map<String,Object> getHontLog(ParamVo param ){
        Map<String,Object> data=new HashMap<>();
        String dateType="";
        if(ParamVo.day==param.getSelectType()){
            dateType="%Y-%m-%d %H:00:00";
        }else {
            dateType="%Y-%m-%d";

        }
        List<Map<String, Object>>  totalHontLog= indexMapper.totalHontLog(dateType,param.getBeginDate(),param.getEndDate());
        List<Map<String, Object>> totalHontLogOnDePart= indexMapper.totalHontLogOnDePart(param.getBeginDate(),param.getEndDate());
        List<Map<String, Object>> result=  getDateTimeLine(totalHontLog,param);
        data.put("barChart",result);
        data.put("data",totalHontLogOnDePart);
    return data;
    }
    public List<Map<String, Object>> getDateTimeLine( List<Map<String, Object>> items,ParamVo param){
        List<Map<String, Object>> data=new ArrayList<>();
        switch(param.getSelectType()){
            case ParamVo.day: {
              String date=  DateUtils.getCurrentDate();

                for (int i = 0; i <24 ; i++) {
                    String flag=i+":00:00";
                    if(i<10){
                        flag="0"+flag;
                    }
                    Map<String, Object> map=new HashMap<>();
                    String time=date+" "+flag;
                    if(items.size()>0){
                        List<Map<String, Object>> list=   items.stream().filter(t->time.equals(t.get("time"))).collect(Collectors.toList());
                        if(list.size()>0){
                            data.addAll(list);
                            continue;
                        }
                    }
                    map.put("time",time);
                    map.put("count",0);
                    data.add(map);
                }
                break;
            }
            default: {
                LocalDate start = DateUtils.parseLocalDateTime(param.getBeginDate(),DateUtils.DATETIME_FORMATTER).toLocalDate();
                LocalDate end = DateUtils.parseLocalDateTime(param.getEndDate(),DateUtils.DATETIME_FORMATTER).toLocalDate();
                List<LocalDate> dates = Stream.iterate(start, date -> date.plusDays(1))
                        .limit(ChronoUnit.DAYS.between(start, end)+1)
                        .collect(Collectors.toList());
                for(LocalDate item: dates){
                    Map<String, Object> map=new HashMap<>();
                    String time=DateUtils.formatLocalDate(item);
                    if(items.size()>0){
                        List<Map<String, Object>> list=   items.stream().filter(t->time.equals(t.get("time"))).collect(Collectors.toList());
                        if(list.size()>0){
                            data.addAll(list);
                            continue;
                        }
                    }
                    map.put("time",time);
                    map.put("count",0);
                    data.add(map);
                }
                break;
            }
        }
        return data;

    }
    public  Map<String,Object> getInstanceinfoCount(ParamVo param ){
        Map<String,Object> data=new HashMap<>();
        String dateType="";
        if(ParamVo.day==param.getSelectType()){
            dateType="%Y-%m-%d %H:00:00";
        }else {
            dateType="%Y-%m-%d";

        }
        List<Map<String, Object>> totalInstanceinfoCountDay= indexMapper.totalInstanceinfoCount(dateType,param.getBeginDate(),param.getEndDate());
        List<Map<String, Object>> totalInstanceinfoOnDePart= indexMapper.totalInstanceinfoOnDePart(param.getBeginDate(),param.getEndDate());
        List<Map<String, Object>> result=  getDateTimeLine(totalInstanceinfoCountDay,param);
        data.put("barChart",result);
        data.put("data",totalInstanceinfoOnDePart);
        return data;
    }
    public Result<Object> countIndexCentre(ParamVo param ){

        getDateTime(param);
        Map<String,Object> map;
        if(ParamVo.HONTLOG==param.getType()){
           map= getHontLog(param );
        }else {
           map= getInstanceinfoCount(param );

        }
        return ResultUtil.data(map);
    }
    public Result<Object> countIndexBottomAvg(ParamVo param ){
        getDateTime(param);
        List<Map<String, Object>>  countIndexBottomAvg= indexMapper.countIndexBottomAvg(param.getBeginDate(),param.getEndDate());

        return ResultUtil.data(countIndexBottomAvg);
    }
    public Result<Object> countIndexBottomTimeOrder(ParamVo param ){
        getDateTime(param);
        List<Map<String, Object>>  countIndexBottomAvg= indexMapper.countIndexBottomTimeOrder(param.getBeginDate(),param.getEndDate());

        return ResultUtil.data(countIndexBottomAvg);
    }
    public Result<Object> countIndexBottomTime(ParamVo param ){

        Map<String,Object> map=new HashMap<>();
        getDateTime(param);
        List<Map<String, Object>>  countIndexBottomTime= indexMapper.countIndexBottomTime(param.getBeginDate(),param.getEndDate(),param.getFirstRow(),param.getLastRow());
        map.put("data",countIndexBottomTime);
        map.put("total",countIndexBottomTime.size());
        return ResultUtil.data(map);
    }
}
